package com.hicorp.segment.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hicorp.segment.pojo.GlobalOption;
import com.hicorp.segment.service.BaseInterface;
import com.hicorp.segment.utils.BaseSqlOption;
import com.hicorp.segment.utils.BasicSqlOption;
import com.hicorp.segment.utils.ResultBean;
import com.hicorp.segment.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Method;
import java.util.List;

import static com.hicorp.segment.utils.BasicSqlOption.selectAll;

@Service
@Slf4j
public class BaseInterfaceImpl implements BaseInterface {

    private final BaseSqlOption baseSqlOption;

    public BaseInterfaceImpl(BaseSqlOption baseSqlOption) {
        this.baseSqlOption = baseSqlOption;
    }

    /**
     * 查询所有
     *
     * @param tableName 表名
     * @return 返还查询的数据
     */
    @Override
    public ResultBean<List<?>> queryAll(String tableName) {
        List<?> result;
        try {
            result = baseSqlOption.selectAll(tableName);
            return new ResultBean<>(result);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, e.getMessage());
        }
    }

    /**
     * 新增单条数据
     *
     * @param tableName 表名
     * @param record    新增的数据内容
     * @return 是否新增成功
     */
    @Override
    public ResultBean<Object> insert(String tableName, Object record) {
        try {
            Object insertRecord = baseSqlOption.changeSingleRecord(tableName, record, GlobalOption.INSERT);
            return new ResultBean<>(insertRecord);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, e.getMessage());
        }
    }

    /**
     * 批量新增
     *
     * @param tableName 表名
     * @param records   批量新增的数据
     * @return 是否新增成功
     */
    @Override
    public ResultBean<List<?>> insertList(String tableName, List<?> records) {
        try {
            List<?> insertRecordList = baseSqlOption.changeBatchRecord(tableName, records, GlobalOption.INSERT_LIST);
            return new ResultBean<>(insertRecordList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, e.getMessage());
        }
    }

    /**
     * 编辑单条记录
     *
     * @param tableName 表名
     * @param id        被编辑的数据的id
     * @param record    被编辑的数据类容
     * @return 是否编辑成功
     */
    @Override
    public ResultBean<Object> update(String tableName, Long id, Object record) {
        try {
            Object updateRecord = baseSqlOption.changeSingleRecord(tableName, record, GlobalOption.UPDATE);
            return new ResultBean<>(updateRecord);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, e.getMessage());
        }
    }

    @Override
    public Object queryInfo(String tableName) {
        return selectAll(tableName, log);
    }

    @Override
    public Object batchDeleteRecord(String tableName, List<Long> ids) {
        try {
            Class<?> mapperClass = getClass("mapper", tableName, "Mapper");
            Class<?> DataClass = getClass("pojo.po", tableName);
            char[] chars = tableName.toCharArray();
            chars[0] = Character.toLowerCase(chars[0]);
            String MapperName = String.valueOf(chars) + "Mapper";
            Object mapper = SpringUtil.getBean(MapperName);
            // 声明Example
            Example example = new Example(DataClass);
            // 获取条件对象
            Example.Criteria criteria = example.createCriteria();
            // 设置条件,第一个是pojo的属性名,第二个参数是条件
            criteria.andIn("id", ids);
            Method method = mapperClass.getMethod("deleteByExample", Object.class);
            return method.invoke(mapper, example);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * @param packageName 包名, 例: pojo、dto、service.impl
     * @param fileName    文件名
     * @return Class<?> 类
     */
    public Class<?> getClass(String packageName, String fileName) throws ClassNotFoundException {
        return Class.forName("com.hicorp.segment." + packageName + "." + fileName);
    }

    /**
     * @param packageName 包名, 例: pojo、dto、service.impl
     * @param fileName    文件名
     * @param fileSuffix  文件后缀名, 例如: Mapper、DO、Service等后缀名
     * @return Class<?> 类
     */
    public Class<?> getClass(String packageName, String fileName, String fileSuffix) throws ClassNotFoundException {
        return Class.forName("com.hicorp.segment." + packageName + "." + fileName + fileSuffix);
    }

    @Override
    public Object changeRecord(String tableName, String methodName, Object record) {
        try {
            Class<?> mapperClass = Class.forName("com.hicorp.segment.mapper." + tableName + "Mapper");
            Class<?> DataClass = Class.forName("com.hicorp.segment.pojo.po." + tableName);
            char[] chars = tableName.toCharArray();
            chars[0] = Character.toLowerCase(chars[0]);
            String MapperName = String.valueOf(chars) + "Mapper";
            Object mapper = SpringUtil.getBean(MapperName);
            Method method = mapperClass.getMethod(methodName, Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
            Object convertValue = objectMapper.convertValue(record, DataClass);
            return method.invoke(mapper, convertValue);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }

    @Override
    public ResultBean<Object> selectRecords(String tableName, String fieldName, String fieldValue) {
        try {
            // 大驼峰mapper名，用于反射.
            String upperCamelTableName = BasicSqlOption.setCamel2UpperCamel(tableName);

            // 小驼峰mapper名, 用于注入.
            String lowerCamelTableName = BasicSqlOption.setCamel2LowerCamel(tableName);

            // mapper的Class
            Class<?> mapperClass = Class.forName("com.hicorp.segment.mapper." + upperCamelTableName + "Mapper");

            // pojo的Class
            Class<?> pojoClass = Class.forName("com.hicorp.segment.pojo.po." + upperCamelTableName);

            String mapperName = lowerCamelTableName + "Mapper";

            // 利用Spring静态方法注入mapper
            Object mapper = SpringUtil.getBean(mapperName);

            // 声明Example
            Example example = new Example(pojoClass);
            // 获取条件对象
            Example.Criteria criteria = example.createCriteria();

            // 利用反射动态传入方法
            Class<?> criteriaClass = Class.forName("tk.mybatis.mapper.entity.Example$Criteria");
            Method criteriaMethod = criteriaClass.getMethod("andLike", String.class, String.class);
            criteriaMethod.invoke(criteria, fieldName, "%" + fieldValue + "%");
            Method method = mapperClass.getMethod("selectByExample", Object.class);
            return new ResultBean<>(method.invoke(mapper, example));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询失败!");
        }
    }
}
